package org.goodsl.deploymap

import org.goodsl.deploymap.parse.EnvDelegate
import org.goodsl.deploymap.parse.ModuleDelegate
import org.goodsl.deploymap.parse.ServiceDelegate

/**
 * Created with IntelliJ IDEA.
 * User: Simon Xiao
 * Date: 12-12-19
 * Time: 上午11:38
 * Copyright goodsl.org 2012~2020
 */
class Parser {

    static AppSystem parse(ScriptLoader loader) {

        AppSystem sys = new AppSystem()

        HashMap<String, Boolean> parsedMap = new HashMap<String, Boolean>()

        loader.scripts().each {
            parseOne(it, loader, sys, parsedMap)
        }

        sys.envs.values().each {
            it.buildServiceRelation()
        }
        return sys
    }

    private static void parseOne(String scriptName, ScriptLoader loader, AppSystem sys,
                                 HashMap<String, Boolean> parsedMap) {
        if (parsedMap.containsKey(scriptName))
            return
        String scriptText = loader.load(scriptName)
        Script dslScript = new GroovyShell().parse(scriptText)
        dslScript.metaClass.include = { String otherScript ->

            parseOne(otherScript, loader, sys, parsedMap)
        }

        dslScript.metaClass.module = { String moduleName, Closure cl ->

            Module newModule = new Module(name: moduleName, system: sys)
            sys.modules.put(moduleName, newModule)

            cl.delegate = newModule
            cl.resolveStrategy = Closure.DELEGATE_FIRST
            cl()

        }

        dslScript.metaClass.service = { String serviceName, Closure cl ->
            Service newService = new Service(name: serviceName, system: sys)
            sys.services.put(serviceName, newService)

            cl.delegate = newService
            cl.resolveStrategy = Closure.DELEGATE_FIRST
            cl()

        }
        dslScript.metaClass.env = { String envName, Closure cl ->
            Env newEnv = new Env(name: envName, system: sys)
            sys.envs.put(envName, newEnv)

            cl.delegate = newEnv
            cl.resolveStrategy = Closure.DELEGATE_FIRST
            cl()

        }

        dslScript.run()

        parsedMap.put(scriptName, true)
    }
}
